﻿#include "synccontrller.h"
#include <QDebug>
#include <QSettings>
#include <QSqlQuery>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QSqlError>
#include "globdataobj.h"

Q_GLOBAL_STATIC(SyncContrller,theInstance)
SyncContrller::SyncContrller() : QObject(nullptr)
{
    //qDebug()<<"构造函数执行";
}

SyncContrller::~SyncContrller(){
    //qDebug()<<"析构函数执行";
}

SyncContrller *SyncContrller::getInstance()
{
    return theInstance();
}

void SyncContrller::syncAllTypeData()
{
    //qDebug()<<"同步数据";
    QSettings settings;
    QString serverAddr = settings.value("cloud/serverAddr").toString();
    QSqlQuery query(dbtools->getDb());
    query.prepare("select * from mytypes");
    query.exec();
    QJsonObject body;
    QJsonArray array;

    while(query.next()){
        QJsonObject jo;
        jo.insert("id",query.value("id").toString());
        jo.insert("type_name",query.value("type_name").toString());
        jo.insert("firsttime",query.value("firsttime").toString());
        jo.insert("lasttime",query.value("lasttime").toString());
        jo.insert("icon",query.value("icon").toString());
        jo.insert("sync_time",query.value("sync_time").toString());
        jo.insert("synced",query.value("synced").toString());
        jo.insert("del",query.value("del").toString());
        array.append(jo);
    }
    body.insert("account",settings.value("cloud/account").toString());
    body.insert("data",array);

    //发送post请求
    QByteArray allTypes = QString("data=").append( QJsonDocument(body).toJson()).toUtf8();

    QNetworkRequest request;
    QNetworkAccessManager *naManager = new QNetworkAccessManager(this);
    QMetaObject::Connection connRet = QObject::connect(naManager,SIGNAL(finished(QNetworkReply*)),
                                                       this,SLOT(syncAllTypeDataRequestFinished(QNetworkReply*)));
    Q_ASSERT(connRet);

    request.setUrl(QUrl("http://"+serverAddr+":8080/onepassx/sync/syncTypes"));

    //naManager->put(request,data.toUtf8());
    naManager->post(request,allTypes);
}



void SyncContrller::setDBtool(Dbtools *db)
{
    qDebug()<<"设置数据库";
    dbtools=db;
}

void SyncContrller::syncAllTypeDataRequestFinished(QNetworkReply *r)
{
    QVariant statusCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(statusCode.isValid()){
        qDebug()<<"status code:"<<statusCode.toInt();
    }
    QVariant reason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if(reason.isValid()){
        qDebug()<<"reason="<<reason;
    }
    QNetworkReply::NetworkError err = r->error();
    if(err!=QNetworkReply::NoError){
        qDebug()<<"Failed: "<<r->errorString();
        emit syncAllTypeDataFail(QString("Failed: ").append(r->errorString()));
    }else{
        QString retStr = r->readAll();
        //qDebug()<<retStr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(retStr.toUtf8());
        if(jsonDoc.isObject()){
            QString updateSql = "update mytypes set type_name=:type_name,"
                                "lasttime=:lasttime,icon=:icon,sync_time=:sync_time,synced='Y',del=:del "
                                "where id=:id";
            QString insertSql = "insert into mytypes (id,type_name,firsttime,lasttime,icon,sync_time,synced,del) values "
                                "(:id,:type_name,:firsttime,:lasttime,:icon,:sync_time,'Y',:del)";
            QJsonObject jo = jsonDoc.object();
            if(jo.value("flag").toBool()){
                QJsonArray retdata = jo.value("retdata").toArray();


                //获取本地所有记录
                QSqlQuery query(dbtools->getDb());
                query.prepare("select * from mytypes");
                query.exec();
                QJsonObject body;
                QJsonArray array;

                while(query.next()){
                    QJsonObject jo;
                    jo.insert("id",query.value("id").toString());
                    jo.insert("type_name",query.value("type_name").toString());
                    jo.insert("firsttime",query.value("firsttime").toString());
                    jo.insert("lasttime",query.value("lasttime").toString());
                    jo.insert("icon",query.value("icon").toString());
                    jo.insert("sync_time",query.value("sync_time").toString().isEmpty()?"0":query.value("sync_time").toString());
                    jo.insert("del",query.value("del").toString());
                    array.append(jo);
                }
                bool exist = false;
                for(int x=0;x<retdata.count();x++){
                    exist = false;
                    QJsonObject rjo = retdata.at(x).toObject();

                    for(int u=0;u<array.count();u++){
                        QJsonObject ujo = array.at(u).toObject();
                        if(ujo.value("id").toString()==rjo.value("id").toString()){
                            //在本地库找到了与远程库相同的项
                            //比较两个项的时间戳
                            //qDebug()<<rjo.value("sync_time").toString().toDouble()<<","<<ujo.value("sync_time").toString().toDouble();
                            if(rjo.value("sync_time").toString().toDouble()>ujo.value("sync_time").toString().toDouble()){
                                //远程项比本地项新,执行更新
                                query.clear();
                                query.prepare(updateSql);
                                query.bindValue(":type_name",rjo.value("type_name").toString());
                                query.bindValue(":lasttime",rjo.value("lasttime").toString());
                                query.bindValue(":icon",rjo.value("icon").toString());
                                query.bindValue(":sync_time",rjo.value("sync_time").toString());
                                query.bindValue(":id",rjo.value("id").toString());
                                query.bindValue(":del",rjo.value("del").toString());
                                query.exec();

                            }
                            exist = true;
                            break;
                        }

                    }

                    //在本地没找到，说明需要新增
                    if(!exist){
                        query.clear();
                        query.prepare(insertSql);
                        query.bindValue(":id",rjo.value("id").toString());
                        query.bindValue(":type_name",rjo.value("type_name").toString());
                        query.bindValue(":firsttime",rjo.value("firsttime").toString());
                        query.bindValue(":lasttime",rjo.value("lasttime").toString());
                        query.bindValue(":icon",rjo.value("icon").toString());
                        query.bindValue(":sync_time",rjo.value("sync_time").toString());
                        query.bindValue(":del",rjo.value("del").toString());
                        query.exec();
                    }

                }
                emit syncAllTypeDataSuccess();
            }else{
                emit syncAllTypeDataFail(jo.value("msg").toString());
            }
        }
    }
}
void SyncContrller::syncAllItemData()
{
    //qDebug()<<"同步数据";
    QSettings settings;
    QString serverAddr = settings.value("cloud/serverAddr").toString();
    QSqlQuery query(dbtools->getDb());
    query.prepare("select * from myitems");
    query.exec();
    QJsonObject body;
    QJsonArray array;

    while(query.next()){
        QJsonObject jo;
        jo.insert("id",query.value("id").toString());
        jo.insert("account",query.value("account").toString());
        jo.insert("pass",query.value("pass").toString());
        jo.insert("firsttime",query.value("firsttime").toString());
        jo.insert("lasttime",query.value("lasttime").toString());
        jo.insert("sync_time",query.value("sync_time").toString());
        jo.insert("synced",query.value("synced").toString());
        jo.insert("type_id",query.value("type_id").toString());
        jo.insert("beizhu",query.value("beizhu").toString());
        jo.insert("del",query.value("del").toString());
        array.append(jo);
    }
    body.insert("account",settings.value("cloud/account").toString());
    body.insert("data",array);

    //发送post请求
    QByteArray allTypes = QString("data=").append( QJsonDocument(body).toJson()).toUtf8();

    QNetworkRequest request;
    QNetworkAccessManager *naManager = new QNetworkAccessManager(this);
    QMetaObject::Connection connRet = QObject::connect(naManager,SIGNAL(finished(QNetworkReply*)),
                                                       this,SLOT(syncAllItemDataRequestFinished(QNetworkReply*)));
    Q_ASSERT(connRet);

    request.setUrl(QUrl("http://"+serverAddr+":8080/onepassx/sync/syncItems"));

    //naManager->put(request,data.toUtf8());
    naManager->post(request,allTypes);
}

void SyncContrller::syncAllItemDataRequestFinished(QNetworkReply *r)
{
    QVariant statusCode = r->attribute(QNetworkRequest::HttpStatusCodeAttribute);
    if(statusCode.isValid()){
        qDebug()<<"status code:"<<statusCode.toInt();

    }
    QVariant reason = r->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
    if(reason.isValid()){
        qDebug()<<"reason="<<reason;
    }
    QNetworkReply::NetworkError err = r->error();
    if(err!=QNetworkReply::NoError){
        qDebug()<<"Failed: "<<r->errorString();
        emit syncAllItemDataFail(QString("Failed: ").append(r->errorString()));
    }else{
        QString retStr = r->readAll();
        //qDebug()<<retStr;
        QJsonDocument jsonDoc = QJsonDocument::fromJson(retStr.toUtf8());
        if(jsonDoc.isObject()){
            QString updateSql = "update myitems set account=:account,"
                                "lasttime=:lasttime,pass=:pass,sync_time=:sync_time,synced='Y', "
                                "type_id=:type_id,beizhu=:beizhu,del=:del  "
                                "where id=:id";
            QString insertSql = "insert into myitems (id,account,pass,firsttime,lasttime,type_id,beizhu,sync_time,synced,del) values "
                                "(:id,:account,:pass,:firsttime,:lasttime,:type_id,:beizhu,:sync_time,'Y',:del)";
            QJsonObject jo = jsonDoc.object();
            if(jo.value("flag").toBool()){
                QJsonArray retdata = jo.value("retdata").toArray();


                //获取本地所有记录
                QSqlQuery query(dbtools->getDb());
                query.prepare("select * from myitems");
                query.exec();
                QJsonObject body;
                QJsonArray array;

                while(query.next()){
                    QJsonObject jo;
                    jo.insert("id",query.value("id").toString());
                    jo.insert("account",query.value("account").toString());
                    jo.insert("pass",query.value("pass").toString());
                    jo.insert("firsttime",query.value("firsttime").toString());
                    jo.insert("lasttime",query.value("lasttime").toString());
                    jo.insert("type_id",query.value("type_id").toString());
                    jo.insert("beizhu",query.value("beizhu").toString());
                    jo.insert("synced",query.value("synced").toString());
                    jo.insert("sync_time",query.value("sync_time").toString().isEmpty()?"0":query.value("sync_time").toString());
                    jo.insert("del",query.value("del").toString());
                    array.append(jo);
                }
                bool exist = false;
                for(int x=0;x<retdata.count();x++){
                    exist = false;
                    QJsonObject rjo = retdata.at(x).toObject();

                    for(int u=0;u<array.count();u++){
                        QJsonObject ujo = array.at(u).toObject();
                        if(ujo.value("id").toString()==rjo.value("id").toString()){
                            //在本地库找到了与远程库相同的项
                            //比较两个项的时间戳
                            //qDebug()<<rjo.value("sync_time").toString().toDouble()<<","<<ujo.value("sync_time").toString().toDouble();
                            if(rjo.value("sync_time").toString().toDouble()>ujo.value("sync_time").toString().toDouble()){
                                //远程项比本地项新,执行更新
                                query.clear();
                                query.prepare(updateSql);
                                query.bindValue(":account",rjo.value("account").toString());
                                query.bindValue(":lasttime",rjo.value("lasttime").toString());
                                query.bindValue(":pass",rjo.value("pass").toString());
                                query.bindValue(":sync_time",rjo.value("sync_time").toString());
                                query.bindValue(":type_id",rjo.value("type_id").toString());
                                query.bindValue(":beizhu",rjo.value("beizhu").toString());
                                query.bindValue(":id",rjo.value("id").toString());
                                query.bindValue(":del",rjo.value("del").toString());
                                query.exec();

                                QSqlError error =  query.lastError();
                                if(error.isValid()){
                                    qDebug()<<error.text();
                                }

                            }
                            exist = true;
                            break;
                        }

                    }

                    //在本地没找到，说明需要新增
                    if(!exist){
                        query.clear();
                        query.prepare(insertSql);
                        query.bindValue(":id",rjo.value("id").toString());
                        query.bindValue(":account",rjo.value("account").toString());
                        query.bindValue(":pass",rjo.value("pass").toString());
                        query.bindValue(":firsttime",rjo.value("firsttime").toString());
                        query.bindValue(":lasttime",rjo.value("lasttime").toString());
                        query.bindValue(":type_id",rjo.value("type_id").toString());
                        query.bindValue(":beizhu",rjo.value("beizhu").toString());
                        query.bindValue(":sync_time",rjo.value("sync_time").toString());
                        query.bindValue(":synced",rjo.value("synced").toString());
                        query.bindValue(":del",rjo.value("del").toString());
                        query.exec();
                    }

                }
                emit syncAllItemDataSuccess();
            }else{
                emit syncAllItemDataFail(jo.value("msg").toString());
            }
        }
    }
}
